#include "Spatial.h"

NS_B2D_BEGIN

B2D_OBJECT_IMPL(Spatial, Object)
	
Spatial::Spatial(void)
	: mPosition(0,0)
	, mRotation(0)
	, mScale(1,1)
	, mTransformDirty(TransformFlag::ALL)
{
}

Spatial::~Spatial(void)
{
}

void Spatial::setPosition(const vec2& v)
{
	setPosition(v.x, v.y);
}

void Spatial::setPositionX(float x)
{
	setPosition(x, mPosition.y);
}

void Spatial::setPositionY(float y)
{
	setPosition(mPosition.x, y);
}

void Spatial::setPosition(float x, float y)
{
	mPosition.x = x;
	mPosition.y = y;
	markTransformDirty(POSITION);
}

void Spatial::move(const vec2& dd)
{
	setPosition(mPosition.x+dd.x, mPosition.y+dd.y);
}

void Spatial::move(float dx, float dy)
{
	setPosition(mPosition.x+dx, mPosition.y+dy);
}

void Spatial::setRotation(float r)
{
	mRotation = r;
	markTransformDirty(ROTATION);
}

void Spatial::rotate(float dr)
{
	setRotation(mRotation+dr);
}

void Spatial::setScale(const vec2& s)
{
	setScale(s.x, s.y);
}

void Spatial::setScaleX(float x)
{
	setScale(x, mScale.y);
}

void Spatial::setScaleY(float y)
{
	setScale(mScale.x, y);
}

void Spatial::setScale(float sx, float sy)
{
	mScale.x = sx;
	mScale.y = sy;
	markTransformDirty(SCALE);
}

void Spatial::setScale(float s)
{
	setScale(s, s);
}

void Spatial::scale(const vec2& ds)
{
	setScale(mScale.x*ds.x, mScale.y*ds.y);
}

void Spatial::scale(float dsx, float dsy)
{
	setScale(mScale.x*dsx, mScale.y*dsy);
}

void Spatial::scale(float ds)
{
	setScale(mScale.x*ds, mScale.y*ds);
}

const mat4& Spatial::getTransform(void) const
{
	if( mTransformDirty != TransformFlag::NONE )
	{
		updateTransform(mTransform);
		mTransformDirty = TransformFlag::NONE;
	}
	return mTransform;
}


vec2 Spatial::worldToLocal(const vec2& world) const
{
	return ( inverse(getTransform()) * vec4(world.x, world.y, 0, 1)).swizzle(X,Y);
}


vec2 Spatial::localToWorld(const vec2& local) const
{
	return (getTransform() * vec4(local.x, local.y, 0, 1)).swizzle(X,Y);
}

void Spatial::updateTransform(mat4& transform) const
{
	transform = 
		glm::translate(mPosition.x, mPosition.y, 0.f) *
		glm::rotate(degrees(mRotation), vec3(0.f,0.f,1.f)) *
		glm::scale(mScale.x, mScale.y, 1.0f);
}

void Spatial::markTransformDirty(char flags)
{
	mTransformDirty |= flags;
	transformed(*this, flags);
}

NS_B2D_END